﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace cooc
{
    public static class BinaryReaderHelper
    {
        public static IRCMessage ReadMessage(this BinaryReader me)
        {
            return new IRCMessage() { user = me.ReadString(), message = me.ReadString() };
        }

        public static void WriteMessage(this BinaryWriter me, IRCMessage msg)
        {
            me.Write(msg.user);
            me.Flush();
            me.Write(msg.message);
            me.Flush();
        }
    }

    public class DeamonServer
    {
        static Queue<IRCMessage> revc_pending = new Queue<IRCMessage>();
        static Queue<IRCMessage> send_pending = new Queue<IRCMessage>();
        static TcpListener listener;
        static IRCServer bot;
        Thread recive_thread = new Thread(RecivingLoop);
        Thread send_thread = new Thread(SendingLoop);
        public static bool workstatus;
        public static bool recvstatus;
        private static LogUtil logger;

        public DeamonServer(int port)
        {

            logger = new LogUtil(File.OpenWrite(Path.Combine(Environment.CurrentDirectory, "log", DateTime.Now.ToString("yyyy-MM-dd hh.mm.ss") + ".log")));

            //listen for connection
            listener = new TcpListener(IPAddress.Any, port);
            logger.info($"Listening on port {port}");

            bot = new IRCServer();
            logger.info($"Create IRC Server done.");
            bot.ReciveMessageEvt += Bot_ReciveMessageEvt;

        }

        public void Start()
        {
            workstatus = true;
            recvstatus = false;

            listener.Start();
            logger.info("Listening Start");


            bot.Connect();
            logger.info("Connect to osu IRC.");

            recive_thread.Start();
            logger.info("Recive thread started");

            send_thread.Start();
            logger.info("Send thread started");

            while (workstatus) { Thread.Sleep(10); }

        }

        public void Stop()
        {
            logger.info("Stop threads");
            workstatus = false;
            logger.info("Stop socket");
            listener.Stop();
            logger.info("stop IRC socket");
            bot.Disconnect();
            logger.info("Stoped");

        }

        public static void RecivingLoop()
        {
            logger.info("Waiting for connection.");
            TcpClient conn;
            try
            {
                conn = listener.AcceptTcpClient();
            }
            catch
            {
                logger.info("Listening stoped");
                return;
            }

            logger.info("Accepted connection");
            recvstatus = true;
            NetworkStream clientStream = conn.GetStream();
            BinaryReader br = new BinaryReader(clientStream);
            BinaryWriter bw = new BinaryWriter(clientStream);
            logger.info("Create stream done");

            while (workstatus && conn.Connected)
            {
                logger.info("Peeking client server message");
                IRCMessage msg = br.ReadMessage();
                send_pending.Enqueue(msg);
                logger.info($"Added to queue, <{msg.user}> {msg.message}");

                logger.info($"Peeking osu irc message Pending:{revc_pending.Count}");
                while (revc_pending.Count > 0)
                {
                    bw.WriteMessage(revc_pending.Dequeue());
                }
                logger.info($"Now queue pending: {revc_pending.Count}");
            }
        }

        public void PrintStauts()
        {
            logger.info($"osu irc server: {bot.GetServerStatus()}");
            logger.info($"Pending (osu)->(client) queue {revc_pending.Count}");
            logger.info($"client server: {recvstatus}");
            logger.info($"Pending (client)->(osu) queue {send_pending.Count}");
        }

        public static void SendingLoop()
        {
            while(workstatus)
            {
                if (recvstatus && bot.GetServerStatus() && send_pending.Count > 0)
                {
                    logger.info($"Peeking client serever message Pending {send_pending.Count}");
                    IRCMessage msg = send_pending.Dequeue();
                    bot.SendMessage("PRIVMSG " + msg.user + " :" + msg.message);
                }
                Thread.Sleep(100);
            }
        }

        private void Bot_ReciveMessageEvt(string user, string msg)
        {
            logger.info($"Added to queue, <{user}> {msg}");
            revc_pending.Enqueue(new IRCMessage() { user = user, message = msg });
        }
    }
}
